#pragma once
#include <vector>
#include <d3dx9.h>

class Node
{
protected:
	std::vector<Node*> childs;
	Node* parent;
	bool needRebuild;
	D3DXMATRIX transform;
	D3DXQUATERNION rotation;
	D3DXVECTOR3 scale;
	D3DXVECTOR3 position;
public:

	Node()
		:needRebuild(false), parent(0), rotation(0,0,0,1), scale(1,1,1), position(0,0,0)
	{
		D3DXMatrixIdentity(&transform);
	}
	~Node()
	{
	}

	void SetParent( Node *par )
	{
		parent = par;
	}
	Node* GetParent()
	{
		return parent;
	}

	void AddChild(Node* child)
	{
		if( child->GetParent() )
			child->GetParent()->RemoveChildren(child);
		childs.push_back(child);
	}

	void RemoveChildren( Node *child )
	{
		std::vector<Node*>::iterator i;
		for( i = childs.begin(); i != childs.end(); ++i )
			if( (*i) == child )
				childs.erase(i);
	}
	
	void BuildTransform()
	{
		if(needRebuild)
		{
			D3DXMatrixRotationQuaternion(&transform,&rotation);
			
			transform.m[3][0] = position.x;
			transform.m[3][1] = position.y;
			transform.m[3][2] = position.z;
			transform.m[3][3] = 1;

			D3DXMATRIX scaleMtr;
			D3DXMatrixScaling(&scaleMtr, scale.x,  scale.y, scale.z );
			transform = transform * scaleMtr;

			needRebuild = false;
		}
	}

	void SetPosition( float x, float y, float z )
	{
		position.x = x;
		position.y = y;
		position.z = z;
		needRebuild = true;
	}

	void SetRotation( D3DXQUATERNION rot )
	{
		rotation = rot;
		needRebuild = true;
	}

	void SetScale( float x, float y, float z )
	{
		scale.x = x;
		scale.y = y;
		scale.z = z;
		needRebuild = true;
	}

	D3DXVECTOR3 GetPosition()
	{
		return position;
	}

	D3DXQUATERNION GetRotation()
	{
		return rotation;
	}

	D3DXVECTOR3 GetScale()
	{
		return scale;
	}

	D3DXMATRIX GetTransform()
	{
		return transform;
	}

	static void BuildAbsoluteTransform(Node *node, D3DXMATRIX parentTransform, bool flag)
	{
		if( node->needRebuild )
			flag = true;
		node->BuildTransform();

		if(flag)
		{
			node->transform = parentTransform * node->transform;
		}

		std::vector<Node*>::iterator i;
		for( i = node->childs.begin(); i != node->childs.end(); ++i )
		{
			(*i)->BuildAbsoluteTransform( (*i), node->transform, flag );
		}
	}


};